/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package com.linktco.prison.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.base.Joiner;
import com.linktco.common.constant.Digit;
import com.linktco.common.utils.U;
import com.linktco.prison.entity.CabinetUser;
import com.linktco.prison.entity.CabinetCell;
import com.linktco.prison.entity.CabinetInfo;
import com.linktco.prison.service.ICabinetCellUserService;
import com.linktco.prison.service.ICabinetInfoService;
import com.linktco.prison.vo.CabinetCellVO;
import com.linktco.prison.mapper.CabinetCellMapper;
import com.linktco.prison.service.ICabinetCellService;
import com.linktco.prison.vo.CabinetSided;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 档案柜格 服务实现类
 *
 * @author BladeX
 * @since 2024-12-23
 */
@Service
public class CabinetCellServiceImpl extends BaseServiceImpl<CabinetCellMapper, CabinetCell> implements ICabinetCellService {

    @Lazy
    @Autowired
    private ICabinetInfoService cabinetService;
    @Lazy
    @Autowired
    private ICabinetCellUserService cellUserService;

    @Override
    public IPage<CabinetCellVO> selectCabinetCellPage(IPage<CabinetCellVO> page, CabinetCellVO cabinetCell) {
        return page.setRecords(baseMapper.selectCabinetCellPage(page, cabinetCell));
    }


    @Override
    public CabinetCell getByCellNo(Long cabinetId, String cellNo) {
        return getOne(Wrappers.<CabinetCell>lambdaQuery()
                .eq(CabinetCell::getCabinetId, cabinetId)
                .eq(CabinetCell::getCellNo, cellNo)
                .last("limit 1")
        );
    }


    @Override
    public IPage<CabinetSided> sidedPage(IPage<CabinetSided> page, String cabinetKeyword, String userKeyword) {
        List<CabinetSided> sidedList = baseMapper.sidedPage(page, cabinetKeyword, userKeyword);
        sidedList.forEach(sided -> {
            List<CabinetCellVO> list = baseMapper.listByCabinetId(sided.getCabinetId());
            list.forEach(vo -> fillUser(vo, userKeyword, sided.getCellUsers()));
            sided.setFrontCellList(getFrontCellList(list, sided.getCabinetRows()));
            sided.setBackCellList(getBackCellList(list, sided.getCabinetRows()));
        });
        return page.setRecords(sidedList);
    }

    @Override
    public CabinetSided sidedList(Long cabinetId) {

        CabinetInfo cabinet = cabinetService.getById(cabinetId);

        List<CabinetCellVO> list = baseMapper.listByCabinetId(cabinetId);
        list.forEach(cell -> fillUser(cell, "", cabinet.getCellUsers()));


        return CabinetSided.builder()
                .cabinetId(cabinetId)
                .cabinetName(cabinet.getName())
                .cabinetRows(cabinet.getRowNum())
                .frontCellList(getFrontCellList(list, cabinet.getRowNum()))
                .backCellList(getBackCellList(list, cabinet.getRowNum()))
                .build();

    }

    private List<CabinetSided.CellList> getFrontCellList(List<CabinetCellVO> list, Integer rowNum) {

        List<CabinetSided.CellList> resultList = new ArrayList<>();

        for (int row = 1; row <= rowNum; row++) {
            int finalRow = row;

            List<CabinetCellVO> aList = list.stream()
                    .filter(vo -> vo.getRows().equals(finalRow) && Digit.ONE.equals(vo.getType()))
                    .sorted(Comparator.comparing(CabinetCellVO::getCellNo))
                    .collect(Collectors.toList());

            resultList.add(CabinetSided.buildCellList(aList));
        }


        return resultList;
    }


    private List<CabinetSided.CellList> getBackCellList(List<CabinetCellVO> list, Integer rowNum) {
        List<CabinetSided.CellList> resultList = new ArrayList<>();

        for (int row = 1; row <= rowNum; row++) {
            int finalRow = row;

            List<CabinetCellVO> bList = list.stream()
                    .filter(vo -> vo.getRows().equals(finalRow) && Digit.TWO.equals(vo.getType()))
                    .sorted(Comparator.comparing(CabinetCellVO::getCellNo))
                    .collect(Collectors.toList());

            resultList.add(CabinetSided.buildCellList(bList));
        }

        return resultList;
    }


    private void fillUser(CabinetCellVO cell, String userKeyword, int cellUsers) {
        List<CabinetUser> userList = getUserList(cell.getId());

        if (U.notEmpty(userKeyword)){
            userList.forEach(user -> {
                if (!cell.isOpen()) {
                    cell.setOpen(user.getName().contains(userKeyword));
                }
                if (!cell.isOpen()) {
                    cell.setOpen(user.getIdCard().contains(userKeyword));
                }
                if (!cell.isOpen()) {
                    cell.setOpen(user.getUserNo().contains(userKeyword));
                }
            });
        }

        int step = cellUsers - userList.size();
        cell.setStatus(step == 0 ? 2 : step == cellUsers ? 0 : 1);

        List<String> names = userList.stream().map(CabinetUser::getName).collect(Collectors.toList());
        cell.setUserNames(Joiner.on(",").join(names));

        List<Long> ids = userList.stream().map(CabinetUser::getId).collect(Collectors.toList());
        cell.setUserIds(Joiner.on(",").join(ids));

    }

    private List<CabinetUser> getUserList(Long cellId) {
        return cellUserService.getUserList(cellId);
    }
}
